﻿using System;
using System.Threading;
using System.Collections;
using System.Linq;
using System.Text;

namespace Zadanie4
{
    class Brigde
    {
        private Thread selectThread;

        internal Queue enterNorthboundQueue = Queue.Synchronized(new Queue());
        internal Queue enterSouthboundQueue = Queue.Synchronized(new Queue());
        internal Queue exitNorthboundQueue = Queue.Synchronized(new Queue());
        internal Queue exitSouthboundQueue = Queue.Synchronized(new Queue());

        internal int northboundCount = 0;
        internal int southboundCount = 0;

        public void EnterNorthbound()
        {
            Semaphore semaphore = new Semaphore(0, 1);
            enterNorthboundQueue.Enqueue(semaphore);
            semaphore.WaitOne();
        }

        public void ExitNorthbound()
        {
            Semaphore semaphore = new Semaphore(0, 1);
            exitNorthboundQueue.Enqueue(semaphore);
            semaphore.WaitOne();
        }

        public void EnterSouthbound()
        {
            Semaphore semaphore = new Semaphore(0, 1);
            enterSouthboundQueue.Enqueue(semaphore);
            semaphore.WaitOne();
        }

        public void ExitSouthbound()
        {
            Semaphore semaphore = new Semaphore(0, 1);
            exitSouthboundQueue.Enqueue(semaphore);
            semaphore.WaitOne();
        }

        private void Select()
        {
            while (true)
            {
                if (southboundCount == 0) acceptEnterNorthbound();
                acceptExitNorthbound();

                if (northboundCount == 0) acceptEnterSouthbound();
                acceptExitSouthbound();
            }
        }

        private void acceptExitSouthbound()
        {
            if (exitSouthboundQueue.Count > 0)
            {
                southboundCount--;
                ((Semaphore)exitSouthboundQueue.Dequeue()).Release();
            }
        }

        private void acceptExitNorthbound()
        {
            if (exitNorthboundQueue.Count > 0)
            {
                northboundCount--;
                ((Semaphore)exitNorthboundQueue.Dequeue()).Release();
            }
        }

        private void acceptEnterSouthbound()
        {
            if (enterSouthboundQueue.Count > 0)
            {
                southboundCount++;
                ((Semaphore)enterSouthboundQueue.Dequeue()).Release();
            }
        }

        private void acceptEnterNorthbound()
        {
            if (enterNorthboundQueue.Count > 0)
            {
                northboundCount++;
                ((Semaphore)enterNorthboundQueue.Dequeue()).Release();
            }
        }

        public void Run()
        {
            selectThread = new Thread(new ThreadStart(Select));
            selectThread.Start();
        }

        public void Stop()
        {
            selectThread.Abort();
        }
    }
}
